#include "round.h"

card deal(struct board *board, struct player *player) {
    card c = board_pop_card(board);
    player_push_card(player, c);
    return c;
}

card discard(struct player *player, struct board *board) {
    card c = player_pop_card(player);
    board_push_card(board, c);
    return c;
}

void play_one_round(struct player *players, struct board *board, struct args args) {
    FILE *fp = args.log_filep;

    board_reshuffle(board);
    if (args.mode == MODE_DEMO) disp_shuffle(board);
    log_shuffle(fp, board);

    disp_game_header(), log_game_header(fp);
    // Deal cards
    for (int i = 0; i < args.n; i++) {
        for (int j = 0; j < args.c; j++) {
            deal(board, &players[i]);
        }
        if (args.mode == MODE_DEMO) disp_draw_cards(&players[i], args.c);
        log_draw_cards(fp, &players[i], args.c);
    }

    // Draw first player
    if (board->next_player == NULL) {
        int min = CARD_PER_DECK + 1;
        for (int i = 0; i < args.n; i++) {
            card c = board_pop_card(board);
            // Show card c to player i
            disp_show_card(i, c), log_show_card(fp, i, c);
            if (c.order < min) {
                min = c.order;
                board->next_player = &(players[i]);
            }
            board_push_card(board, c);
        }
    }

    // Random flip
    card c = board_pop_card(board);
    disp_init_result(c), log_init_result(fp, c);
    board_push_card(board, c);

    if (args.mode == MODE_NORMAL) disp_wait("Game Start!");

    while (true) {
        struct player *cur_player = board->next_player;
        char info[128];
        sprintf(info, "Now, it's player %d's turn!", cur_player->id);
        if (args.mode == MODE_NORMAL) disp_cls(), disp_wait(info);
        disp_turn_header(cur_player, board), log_turn_header(fp, cur_player, board);
        if (!player_can_pop(cur_player, board->top_card, board->force_draw)) {
            // draw cards
            if (!board->force_draw) board->force_draw = 1;
            for (int i = 0; i < board->force_draw; i++) deal(board, cur_player);
            disp_draw_cards(cur_player, board->force_draw), log_draw_cards(fp, cur_player, board->force_draw);
            board->force_draw = 0;
        } else {
            if (args.mode == MODE_NORMAL) {
                card c = {-1, 0};
                do {
                    c = read_card();
                    if (!board_can_play(board, c)) {
                        printf("Error: You cannot play ");
                        disp_card(c);
                        printf("\n");
                    } else if (!player_choose_card(cur_player, c)) {
                        printf("Error: You don't have ");
                        disp_card(c);
                        printf("\n");
                    }
                } while (!board_can_play(board, c) || !player_choose_card(cur_player, c));
            }
            discard(cur_player, board);
            disp_player_played(board, 1, cur_player->id), log_player_played(fp, board, 1, cur_player->id);
            board->force_draw += card_need_draw(board->top_card);
            if (card_is_cancel(board->top_card)) board->force_draw = 0;
        }
        if (args.mode == MODE_NORMAL) disp_wait("Your turn ended!");
        if (cur_player->card_count == 0)
            break;
        else
            board_next_player(board);
    }

    disp_game_summary(players, board, args);
    log_game_summary(fp, players, board, args);

    // Reset players and board
    for (int i = 0; i < args.n; i++) {
        players[i].score -= players[i].card_count;
        while (players[i].card_count) {
            discard(&players[i], board);
        }
    }
    board_reset(board);
}
